package com.stage.helper;


import com.stage.annotation.Column;
import com.stage.annotation.Label;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Scanner;

/**
 * Created by Stage on 2017/3/17.
 */
public class ObjectManager {
    private InputManager inputManager;

    /**
     * 构造方法
     */
    public ObjectManager() {
        inputManager = new InputManager();
    }

    /**
     * 获取字段的注解对象
     *
     * @param annotation
     * @param className
     * @param filedName
     * @return
     */
    public Annotation getFieldAnnotation(Class annotation, String className, String filedName) {
        try {
            Class<?> tempClass = Class.forName(className);
            Field filed = tempClass.getDeclaredField(filedName);
            filed.setAccessible(true);
            if (filed.isAnnotationPresent(annotation)) {
                Annotation label = filed.getAnnotation(annotation);
                return label;
            }
        } catch (ClassNotFoundException | NoSuchFieldException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取该对象有该注解的字段的get方法
     *
     * @param clazz
     * @param list
     * @return
     */
    public Object setAttr(Class<?> clazz, HashMap<Field, Object> list) {
        // Field fields[] = (Field[]) list.keySet().toArray();
        Method methods[] = clazz.getMethods();
        Object person = null;
        try {
            person = clazz.newInstance();
            for (Field filed : list.keySet()) {
                if (filed.getType().getName() == "java.lang.String") {
                    String setter = "set" + inputManager.firstCharToUp(filed.getName());
                    for (Method method : methods) {
                        String methodName = method.getName();
                        if (methodName.equals(setter)) {
                            method.invoke(person, list.get(filed));
                            break;
                        }
                    }
                } else if (filed.getType().getName() == "java.lang.Integer") {
                    String setter = "set" + inputManager.firstCharToUp(filed.getName());
                    for (Method method : methods) {
                        String methodName = method.getName();
                        if (methodName.equals(setter)) {
                            method.invoke(person, (list.get(filed)));
                            break;
                        }
                    }
                } else if (filed.getType().getName() == "java.lang.Boolean") {
                    String setter = "set" + inputManager.firstCharToUp(filed.getName());
                    for (Method method : methods) {
                        String methodName = method.getName();
                        if (methodName.equals(setter)) {
                            method.invoke(person, list.get(filed));
                            break;
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return person;
    }

    /**
     * 获取该对象有该注解的字段的set方法
     *
     * @param obj
     * @param clazz
     * @param annotation
     * @return
     */
    private List<String> getAttr(Object obj, Class<?> clazz, Class annotation) {
        Field fields[] = clazz.getDeclaredFields();
        Method methods[] = clazz.getDeclaredMethods();
        List<String> list = new ArrayList<>();
        try {
            for (Field field : fields) {

                if (field.getType().getName() == "java.lang.Boolean" && field.isAnnotationPresent(annotation)) {
                    String setter = "is" + inputManager.firstCharToUp(field.getName());
                    for (Method method : methods) {
                        String methodName = method.getName();
                        if (methodName.equals(setter)) {
                            list.add(method.invoke(obj).toString());
                            break;
                        }
                    }
                } else if (field.isAnnotationPresent(annotation)) {
                    String setter = "get" + inputManager.firstCharToUp(field.getName());
                    for (Method method : methods) {
                        String methodName = method.getName();
                        if (methodName.equals(setter)) {
                            list.add(method.invoke(obj).toString());
                            break;
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

    /**
     * 通过Label标签来初始化对象
     *
     * @param className
     * @return
     */
    public Object getUserInputByLabel(String className) {
        Object object = null;
        Class<?> tempClass = null;
        try {
            tempClass = Class.forName(className);
            object = tempClass.newInstance();
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        assert tempClass != null;
        Field fields[] = tempClass.getDeclaredFields();
        HashMap<Field, Object> result = new HashMap<>();
        Scanner input = new Scanner(System.in);
        for (Field field : fields) {
            Label label = (Label) this.getFieldAnnotation(Label.class, className, field.getName());
            if (label != null) {
                result.put(field, inputManager.inputObjectByLabel(field.getType().getTypeName(), label));
            }
        }
        assert object != null;
        object = this.setAttr(object.getClass(), result);
        return object;
    }

    public Object getUserInputByColumn(String className) {
        Object object = null;
        Class<?> tempClass = null;
        try {
            tempClass = Class.forName(className);
            object = tempClass.newInstance();
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        assert tempClass != null;
        Field fields[] = tempClass.getDeclaredFields();
        HashMap<Field, Object> result = new HashMap<>();
        for (Field field : fields) {
            Column column = (Column) this.getFieldAnnotation(Column.class, className, field.getName());
            if (column != null) {
                result.put(field, inputManager.inputObjectByColumn(field.getType().getTypeName(), column));
            }
        }
        assert object != null;
        object = this.setAttr(object.getClass(), result);
        return object;
    }

    /**
     * 通过Label标签来显示对象
     *
     * @param object
     */
    public void showObjectByLabel(Object object) {
        List<String> filedResults = new ArrayList<String>();
        Class<?> tempClass = null;
        try {
            tempClass = Class.forName(object.getClass().getName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        assert tempClass != null;
        Field fields[] = tempClass.getDeclaredFields();
        for (Field field : fields) {
            if (field.isAnnotationPresent(Label.class)) {
                Label lb = field.getAnnotation(Label.class);
                filedResults.add(lb.value() + ":");
            }
        }
        if (filedResults != null) {
            print(filedResults, object, Label.class);
        }
    }

    public void showObjectByColumn(Object object) {
        List<String> filedResults = new ArrayList<String>();
        Class<?> tempClass = null;
        try {
            tempClass = Class.forName(object.getClass().getName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        assert tempClass != null;
        Field fields[] = tempClass.getDeclaredFields();
        for (Field field : fields) {
            if (field.isAnnotationPresent(Column.class)) {
                Column column = field.getAnnotation(Column.class);
                filedResults.add(column.value().value() + ":");
            }
        }
        if (filedResults != null) {
            print(filedResults, object, Column.class);
        }
    }

    private void print(List<String> filedResults, Object object, Class annotation) {
        List<String> list2 = this.getAttr(object, object.getClass(), annotation);
        for (int i = 0; i < list2.size(); i++) {
            System.out.println(filedResults.get(i) + list2.get(i));
        }
    }

}


